/**********************************************************************************
// Sprite Source
// 
// Creation:	11 Jul 2007
// Updated:		27 Mai 2011
// Compiler:	Visual Studio 2010
//
// Notes:		Defines a sprite engine
//
**********************************************************************************/

#include "Sprite.h"

/**********************************************************************************/

Sprite::Sprite(char * filename, uint frameWidth, uint frameHeight, uint numColumns, Color colorkey)
{
	// clean the structure
	D3DXIMAGE_INFO imgInfo;
	ZeroMemory(&imgInfo, sizeof(imgInfo));

	// get image info from file
	D3DXGetImageInfoFromFile(filename, &imgInfo);

	// load image into texture
	D3DXCreateTextureFromFileEx(
		D3DGame::GetDevice(),		// direct3d device
		filename,					// image filename
		imgInfo.Width,				// image width
		imgInfo.Height,				// image height
		1,							// mipmap levels (1 for no chain)
		NULL,						// usage (not a render target nor dinamic)
		D3DFMT_UNKNOWN,				// get pixel format from the file
		D3DPOOL_DEFAULT,			// memory pool of the texture
		D3DX_DEFAULT,				// control how the image is filtered
		D3DX_DEFAULT,				// control how the image is filtered for mipmaps
		colorkey.Direct3D(),		// color to replace by transparent
		NULL,						// image file info (already have it)
		NULL,						// color palette
		&texture);					// destination texture

	// no animation and no bounding box by default
	animation = nullptr;
	boundingbox = nullptr;

	// if the image is a sprite sheet then width and height are the  
	// size of a tile, otherwise they are the size of the whole image
	if (frameWidth == 0 || frameHeight == 0)
	{
		width = imgInfo.Width;
		height = imgInfo.Height;
	}
	else
	{
		width = frameWidth;
		height = frameHeight;
	}

	// set the number of columns in the sprite sheet
	// the default valeu is one (single image)
	columns = numColumns;

	rotation = 0.0f;			// rotation angle
	scalingX = 1.0f;			// scaling factor of X coordinate
	scalingY = 1.0f;			// scaling factor of Y coordinate
	type     = ObjSprite;		// type of object for collision detection
}


/**********************************************************************************/

Sprite::~Sprite()
{
	if (texture)
		texture->Release();
}

/**********************************************************************************/

void Sprite::Translate(float dx, float dy)
{  
	x += dx; 
	y += dy; 

	if (boundingbox)
		boundingbox->Translate(dx,dy);
}

/**********************************************************************************/

void Sprite::MoveTo(float px, float py)
{
	x = px;
	y = py;

	if (boundingbox)
		boundingbox->MoveTo(px,py);
}

/**********************************************************************************/

void Sprite::MoveTo(int px, int py)
{
	x = float(px);
	y = float(py);

	if (boundingbox)
		boundingbox->MoveTo(px,py);
}

/**********************************************************************************/

void Sprite::Rotate(float angle)
{ 
	rotation += angle; 
	if (boundingbox)
		boundingbox->Rotate(angle);
} 

/**********************************************************************************/

void Sprite::Scale(float xScale, float yScale)
{ 
	scalingX *= xScale; 
	scalingY *= yScale; 
	if (boundingbox)
		boundingbox->Scale(xScale, yScale);
}

/**********************************************************************************/

void Sprite::Draw(int frame)
{
	// draw position is the sprite position
	int xPos = int(x)-int(D3DGame::viewport.left);
	int yPos = int(y)-int(D3DGame::viewport.top);

	// image source rectangle
	RECT * pframeRect = nullptr;
	RECT frameRect;

	// if there is an anymation not using follow mode 
	// set draw position to the animation position
	if (animation)
	{
		if (!animation->followMode)
		{
			xPos = int(animation->xPos)-int(D3DGame::viewport.left);
			yPos = int(animation->yPos)-int(D3DGame::viewport.top);
		}

		// get current selected frame from animation
		int frame = animation->GetFrame();
				
		frameRect.left   = (frame % columns) * width;
		frameRect.top    = (frame / columns) * height;
		frameRect.right  = frameRect.left + width;
		frameRect.bottom = frameRect.top + height;
		pframeRect = &frameRect;
	}
	else
	{
		frameRect.left   = (frame % columns) * width;
		frameRect.top    = (frame / columns) * height;
		frameRect.right  = frameRect.left + width;
		frameRect.bottom = frameRect.top + height;
		pframeRect = &frameRect;
	}

	// create a translate vector
	D3DXVECTOR2 translation((float) xPos, (float) yPos);

	// create a scale vector
	D3DXVECTOR2 scale(scalingX, scalingY);
	
	// PI divided by 180
	const double PIdiv180 = 0.0174532925194444;

	// convert angle to radians 
	float theta = float(rotation * PIdiv180);

	// create tranformation matrix
	D3DXMATRIX mat;
	D3DXMatrixTransformation2D(&mat, NULL, 0.0f, &scale, NULL, theta, &translation);
	
	// set the center of the texture or tile
	D3DXVECTOR3 center;
	center.x = (width)/2.0f;
	center.y = (height)/2.0f;
	center.z = 0.0f;

	// use the transformations in the draw 
	D3DGame::GetRenderer()->SetTransform(&mat);

	// Draw the texture at the position x, y
	D3DGame::GetRenderer()->Draw(
		texture,								// texture
		pframeRect,								// source rectangle 
		&center,								// center of the texture
		NULL,									// position of the sprite onscreen
		D3DCOLOR_XRGB(255,255,255));			// WHITE mantains the original colors
}

/**********************************************************************************/
